package com.ansion.adapter;

import android.util.SparseArray;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.recyclerview.widget.DiffUtil;
import androidx.recyclerview.widget.RecyclerView;

import com.ansion.view.pin_view.PinnedHeaderAdapter;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

public class TurboAdapter<T extends IAdapterData> extends PinnedHeaderAdapter<TurboAdapter.ViewHolder<T>> {

    private final SparseArray<ITurboItem<ViewHolder<T>>> mTypeCache = new SparseArray<>();
    private ArrayList<T> mData = new ArrayList<>();

    protected TurboAdapter() {
    }

    public static <T extends IAdapterData> TurboAdapter<T> with(@NonNull Collection<ITurboItem> adapters) {
        TurboAdapter<T> adapter = new TurboAdapter<>();
        for (ITurboItem item : adapters) {
            adapter.saveType(item.getType(), item);
        }

        return adapter;
    }

    private void saveType(int key, ITurboItem item) {
        mTypeCache.put(key, item);
    }

    public TurboAdapter<T> setData(Collection<T> data) {
        mData.clear();
        if (data != null) {
            mData.addAll(data);
        }
        return this;
    }

    public TurboAdapter<T> addData(Collection<T> data, int position) {
        if (data != null) {
            mData.addAll(position, data);
        }
        return this;
    }

    public TurboAdapter<T> addData(Collection<T> data) {
        if (data != null) {
            mData.addAll(data);
        }
        return this;
    }

    public ArrayList<T> getData() {
        return mData;
    }

    @NonNull
    @Override
    public ViewHolder<T> onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        ITurboItem<ViewHolder<T>> viewHolderITurboItem = mTypeCache.get(viewType);
        if (viewHolderITurboItem == null) {
            return new EmptyVH(new TextView(parent.getContext()));
        }

        return mTypeCache.get(viewType).getVH(parent);
    }


    @Override
    public void onBindViewHolder(@NonNull ViewHolder<T> holder, int position) {
        holder.bindView(mData.get(position), position);
    }

    @Override
    public void onBindViewHolder(@NonNull ViewHolder<T> holder, int position, @NonNull List<Object> payloads) {
        if (payloads.isEmpty()) {
            holder.bindView(mData.get(position), position);
        } else {
            holder.bindView(mData.get(position), position, payloads);
        }
    }

    @Override
    public int getItemViewType(int position) {
        return mData.get(position).getType();
    }

    @Override
    public int getItemCount() {
        return mData.size();
    }

    @Override
    public boolean isPinnedPosition(int position) {
        if (position < 0) {
            return false;
        }
        return getItemViewType(position) == PIN_TYPE;
    }

    class EmptyVH extends ViewHolder<T> {

        public EmptyVH(View itemView) {
            super(itemView);
        }

        @Override
        public void bindView(T item, int position) {

        }

        @Override
        public void bindView(T item, int position, @NonNull List<Object> payloads) {

        }
    }

    public abstract static class ViewHolder<T extends IAdapterData> extends RecyclerView.ViewHolder {
        public ViewHolder(View itemView) {
            super(itemView);
        }

        public abstract void bindView(T item, int position);

        public void bindView(T item, int position, @NonNull List<Object> payloads) {

        }
    }

    public void updateByDiff(@NonNull DiffUtil.Callback cb, Collection<T> data) {
        DiffUtil.DiffResult diffResult = DiffUtil.calculateDiff(cb, true);
        TurboAdapter<T> tTurboAdapter = setData(data);
        diffResult.dispatchUpdatesTo(tTurboAdapter);
    }
}
